package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.itheima.stock.common.domain.StockExcelDomain;
import com.itheima.stock.common.domain.StockInfoConfig;
import com.itheima.stock.common.enums.ResponseCode;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StockServiceImpl implements StockService {

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    // 获取国内大盘的id标记
    @Autowired
    private StockInfoConfig stockInfoConfig;

    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    /**
     * 查询个股日K线详情
     * @param code
     * @return
     */
    @Override
    public R<List<Map>> getDayKLinData(String code) {
        //1.获取最近一个交易日时间
        DateTime target = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String tDate = DateTimeUtil.getLastDateString4Stock(target);
        List<Map> infos= this.stockRtInfoMapper.getDayKLinData(code,tDate);
        if (CollectionUtils.isEmpty(infos)) {
            return R.error("暂无数据");
        }
        return R.ok(infos);
    }

    /**
     * 查询个股 分时k线详情
     * @param stockCode
     * @return
     */
    @Override
    public R<List<Map>> getStockScreenMinuteSharing(String stockCode) {
        //1.获取最近一个交易日的时间
        DateTime target = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String tDate = DateTimeUtil.getLastDateString4Stock(target);
        tDate = "20220106095500";
        //2.查询数据库
        List<Map> infos = stockRtInfoMapper.getStockScreenMinuteSharing(stockCode,tDate);
        if (CollectionUtils.isEmpty(infos)) {
            return R.error("暂无数据");
        }
        return R.ok(infos);
    }

    /**
     * 如果当前不在交易日内,则以上一个有效交易日进行查询
     * 统计每分钟个股的涨跌幅
     * @return
     */
    @Override
    public R<Map> getStockUpDownScope() {
        //1.获取最近的有效股票交易时间，精确到分钟
        DateTime target = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String last = DateTimeUtil.getLastDateString4Stock(target);
        // 模拟数据
        last = "20220106095500";
        //2.查询数据库,统计个股的涨跌幅
        List<Map> maps = stockRtInfoMapper.getStockUpDownScope(last);
        if (CollectionUtils.isEmpty(maps)) {
            maps=Collections.emptyList();
        }
        // 处理查询结果数据,将无序的涨幅区间变为有序的,如果当前区间内没有数据则填充 0
        //a.获取配置文件中涨幅区间标记
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
        // 定义一个有序的list集合用于存储排序后的数据
        List<Map> newInfos = new ArrayList<>();
        for (String range : upDownRange) {
            // range: "<-7%" 、 "-7~-5%"、 "-5~-3%" 、 "-3~0%" 、"0~3%" 、 "3~5%" 、 "5~7%" 、 ">7%"
            Map orderMap = null;
            for (Map map : maps) { // {"title":"<-7","count":1}
                if (range.equals(map.get("title"))){
                    orderMap = map;
                    break;
                }
            }
            if (orderMap==null) {
                orderMap = new HashMap();
                orderMap.put("title",range);
                orderMap.put("count",0);
            }
            newInfos.add(orderMap);
        }
        //===========================
        //// 将集合中的数据进行转换 // key: "<-7%" "-7~-5%" ....
        //List<Map> finalMaps = maps;
        //List<Map> newInfos =  upDownRange.stream().map(key->{
        //    // 对查询结果进行过滤
        //    Optional<Map> title = finalMaps.stream().filter(map -> key.equals(map.get("title"))).findFirst();
        //    Map map = null;
        //    //判定title是否存在,如果存在则说明当前范围内有个股数据
        //    if (title.isPresent()){
        //        map = title.get();
        //    }else {
        //        map = new HashMap();
        //        map.put("title",key);
        //        map.put("count",0);
        //    }
        //    return map;
        //}).collect(Collectors.toList());
        //============================
        //3.封装响应结果数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("time",target.toString("yyyy-MM-dd HH:mm:ss"));
        map.put("infos",newInfos);
        return R.ok(map);
    }

    /**
     * 成交量对比
     * 沪深两市个股涨跌行情数据查询，查询T日分时成交量与T-1日分时成交量对比数据
     * 简言之，统计两市成交量在每分钟的之和的统计；
     * @return
     */
    @Override
    public R<Map> getStockTravolCompare() {
        //1.获取T日和T-1日的交易时间 (T日的交易时间)
        // 获取最近一个交易日的时间
        DateTime target = DateTimeUtil.getLastDate4Stock(DateTime.now());
        // 格式化日期
        String curTStr = DateTimeUtil.parseToString4Stock(target);
        // todo:模拟数据
        curTStr = "20220103145800";
        //T-1 的日期数据
        String preTStr = DateTimeUtil.parseToString4Stock(DateTimeUtil.getPreviousTradingDay(target));
        preTStr = "20220102145800";
        //2.查询数据库
        //获取T日成交量数据
        List<Map> nowDatas= this.stockMarketIndexInfoMapper.getStockTravol(curTStr);
        if (CollectionUtils.isEmpty(nowDatas)) {
            nowDatas= Collections.emptyList();
        }
        //获取T-1数据
        List<Map> preDatas=this.stockMarketIndexInfoMapper.getStockTravol(preTStr);
        if (CollectionUtils.isEmpty(preDatas)) {
            preDatas=Collections.emptyList();
        }
        //组装数据
        HashMap<String, List> map = new HashMap<>();
        map.put("volList",nowDatas);
        map.put("yesVolList",preDatas);
        return R.ok(map);
    }

    /**
     * 数据导出
     * @param response
     * @param page
     * @param pageSize
     */
    @Override
    public void exportStockExcel(HttpServletResponse response, Integer page, Integer pageSize) throws IOException {
        //1.准备导出的数据信息
        PageHelper.startPage(page,pageSize);
        // 查询当前页的数据信息
        List<Map> maps = stockRtInfoMapper.getStockAll();
        // List<Map>  ---转换---> List<StockExcelDomain>
        List<StockExcelDomain> domains = new ArrayList<>();
        Gson gson = new Gson();
        for (Map map : maps) {
            // map --> StockExcelDomain
            // map -----> json -----> StockExcelDomain
            StockExcelDomain stockExcelDomain = gson.fromJson(gson.toJsonTree(map), StockExcelDomain.class);
            domains.add(stockExcelDomain);
        }
        //2.将数据导出到Excel中,并下载到浏览器本地
        // 文件下载: 两个头一个流
        // 告诉浏览器本次响应的数据类型为Excel文件
        response.setContentType("application/vnd.ms-excel");
        // 设置响应流的编码方式
        response.setCharacterEncoding("utf-8");
        // 设置响应文件的名称
        String filename = URLEncoder.encode("个股涨幅信息","utf-8");
        // 设置文件下载专用头(本次响应携带了附件)
        response.setHeader("content-disposition","attachment;filename="+filename+".xlsx");

        //3.文件导出
        EasyExcel.write(response.getOutputStream(),StockExcelDomain.class)
            .sheet("stockRt").doWrite(domains);
    }

    /**
     * 查询个股涨跌停数据
     * @return
     */
    @Override
    public R<Map> getStockUpDownLimitCount() {
        //获取涨停统计数
        List<Map> upLimit = stockRtInfoMapper.getUpDownLimitCount(1);
        String curDate = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmm"));
        // 如果没有查询到数据则
        if (CollectionUtils.isEmpty(upLimit)) {
            //设置默认值
            HashMap<String, Object> map = new HashMap<>();
            map.put("time",curDate);
            map.put("count",0);
            upLimit.add(map);
        }
        //获取跌停统计数
        List<Map> downLimit= this.stockRtInfoMapper.getUpDownLimitCount(0);
        if (CollectionUtils.isEmpty(upLimit)) {
            //设置默认值
            HashMap<String, Object> map = new HashMap<>();
            map.put("time",curDate);
            map.put("count",0);
            downLimit.add(map);
        }
        //组装数据
        HashMap<String, List<Map>> map = new HashMap<>();
        map.put("upList",upLimit);
        map.put("downList",downLimit);
        return R.ok(map);
    }

    /**
     * 分页查询个数涨跌数据
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public R<PageResult> getStockAll(Integer page, Integer pageSize) {
        /**
         * Pagehelper原理:
         *  Pagehelper采用Mybatis的拦截器机制,对所有查询请求进行拦截
         *  在执行查询请求时,从当前线程上的ThreadLocal中获取分页数据
         *  如果当前线程上有分页的数据,就在当前执行的sql上拼接 limit 进行分页查询
         *  如果当前线程上没有分页的数据,则正常执行sql语句
         */
        //1.将分页数据绑定到当前线程上
        PageHelper.startPage(page,pageSize);
        //2.查询数据库
        List<Map> maps = stockRtInfoMapper.getStockAll();
        if (CollectionUtils.isEmpty(maps)) {
            return R.error("暂无数据");
        }
        //3.获取分页查询的结果
        PageInfo<Map> pageInfo = new PageInfo<>(maps);
        //4.将分页查询结果数据转存到响应结果对象中
        PageResult<Map> result = new PageResult<>(pageInfo);
        return R.ok(result);
    }

    /**
     * 首页:查询个股涨幅 前10
     */
    @Override
    public R<List<Map>> getStockIncrease() {
        //1.获取当前时间
        String lastDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        // 模拟当前时间数据
        lastDate = "";
        //2.发送请求查询个股涨跌幅 前10
        List<Map> maps = stockRtInfoMapper.getStockIncrease();
        if (CollectionUtils.isEmpty(maps)){
            return R.error(ResponseCode.SYSTEM_ERROR.getMessage());
        }
        //3.返回结果
        return R.ok(maps);
    }

    /**
     * 查询板块前10的数据信息
     * @return
     */
    @Override
    public R<List<Map>> getSectorAllLimit() {
        // 获取当前时间
        String lastDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        // 模拟时间
        lastDate = "20211221093000";
        List<Map> maps = stockBlockRtInfoMapper.getSectorAllLimit(lastDate);
        if (CollectionUtils.isEmpty(maps)) {
            return R.error("暂时没有数据");
        }
        return R.ok(maps);
    }

    /**
     * 查询国内大盘数据
     * @return
     */
    @Override
    public R<List<Map>> getInnerStockMarket() {
        //获取最近股票有效交易日，精确到分钟
        String lastAvDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        //设置成有效数据（数据库测试数据可能不存在）
        //lastAvDate="20211228095300";
        List<Map> infos= stockMarketIndexInfoMapper.getInnerStockMarket(stockInfoConfig.getInner(),lastAvDate);
        if (CollectionUtils.isEmpty(infos)) {
            return R.error("暂无数据");
        }
        return R.ok(infos);
    }

    @Override
    public List<StockBusiness> getAllStockBusiness() {
        return stockBusinessMapper.getAll();
    }
}
